package com.hyper_yang.javase.multiThread.notify.lockMethod;

public class Base {
    public static void main(String[] args) throws InterruptedException {
        Bar bar = new Bar();

        Thread cook = new Thread(new CookRunnable(bar), "湘菜大厨");
        Thread cook2 = new Thread(new CookRunnable(bar), "鲁菜大厨");
        Thread waiter = new Thread(new WaiterRunnable(bar), "小二");
        Thread waiter2 = new Thread(new WaiterRunnable(bar), "小四");

        cook.start();
        cook2.start();
        waiter.start();
        waiter2.start();
    }
}

class Bar {
    // 记录菜品的数量
    int count;

    // 实例方法: 锁的对象是 this
    // 静态方法: 锁的对象是当前类对象
    public synchronized void make() {
        try {
            while (this.count >= 10) {
                System.out.println("吧台满了，服务员快端菜");
                this.wait(); // 厨师等待服务员上菜，释放吧台锁
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 做菜
        this.count++;
        System.out.println(Thread.currentThread().getName() + "做了一道菜，吧台上有" + this.count + "道菜");

        // 通知服务员，吧台未空，可以上菜
//        this.notify();
        // 通知所有服务员，吧台未空，可以上菜
        this.notifyAll();
    }

    public synchronized void take() {
        try {
            while (this.count <= 0) {
                System.out.println("吧台空了，厨师快做菜");
                this.wait(); // 服务员等待厨师做菜，释放吧台锁
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 端菜
        this.count--;
        System.out.println(Thread.currentThread().getName() + "端走了一道菜，吧台剩余" + this.count + "道菜");

        // 通知厨师，吧台未满，可以做菜
//        this.notify();
        // 通知所有厨师，吧台未满，可以做菜
        this.notifyAll();
    }
}

class CookRunnable implements Runnable {
    Bar bar;

    public CookRunnable(Bar bar) {
        this.bar = bar;
    }

    @Override
    public void run() {
        while (true)
            this.bar.make();
    }
}

class WaiterRunnable implements Runnable {
    Bar bar;

    public WaiterRunnable(Bar bar) {
        this.bar = bar;
    }

    @Override
    public void run() {
        while (true)
            this.bar.take();
    }
}